package com.penglecode.protobuff;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class SerializedBeanUtils {

	private static final Map<Class<?>,PropertyDescriptor[]> GLOBAL_PROPS_DESC_CACHE = new ConcurrentHashMap<Class<?>,PropertyDescriptor[]>();
	
	public static PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass) {
		try {
			PropertyDescriptor[] pds = GLOBAL_PROPS_DESC_CACHE.get(beanClass);
			if(pds == null){
				pds = Introspector.getBeanInfo(beanClass).getPropertyDescriptors();
				GLOBAL_PROPS_DESC_CACHE.put(beanClass, pds);
			}
			return pds;
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass, Class<?> stopClass) {
		try {
			PropertyDescriptor[] pds = GLOBAL_PROPS_DESC_CACHE.get(beanClass);
			if(pds == null){
				pds = Introspector.getBeanInfo(beanClass, stopClass).getPropertyDescriptors();
				GLOBAL_PROPS_DESC_CACHE.put(beanClass, pds);
			}
			return pds;
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static Map<String,PropertyDescriptor> getPropertyDescriptorMap(Class<?> beanClass) {
		PropertyDescriptor[] pds = getPropertyDescriptors(beanClass);
		if(pds != null && pds.length > 0){
			Map<String,PropertyDescriptor> map = new HashMap<String,PropertyDescriptor>();
			for(PropertyDescriptor pd : pds){
				map.put(pd.getName(), pd);
			}
			return map;
		}
		return null;
	}
	
	public static Map<String,PropertyDescriptor> getPropertyDescriptorMap(Class<?> beanClass, Class<?> stopClass) {
		PropertyDescriptor[] pds = getPropertyDescriptors(beanClass, stopClass);
		if(pds != null && pds.length > 0){
			Map<String,PropertyDescriptor> map = new HashMap<String,PropertyDescriptor>();
			for(PropertyDescriptor pd : pds){
				map.put(pd.getName(), pd);
			}
			return map;
		}
		return null;
	}
	
	public static <T> T newInstance(Class<T> targetClass){
		try {
			return targetClass.newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

}
